home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  49.6 KB  |  1,605 lines

  1. /* $VER: lib.c 2.0 (6.4.2002) by Grzegorz Kraszewski */
  2.  
  3. /****** ttrender.library/background *****************************************
  4. *
  5. *
  6. *   PURPOSE
  7. *
  8. *   The library is fast, AmigaOS friendly TrueType render engine. It has
  9. *   nothing to do with Amiga outline font system. This system has a lot of
  10. *   limitations which make it useless for high speed and quality text output.
  11. *   If someone wants an integration of TrueType with AmigaOS bullet.library
  12. *   like outline font system, should consider using ttf.library. This library
  13. *   opens TrueType font by itself and renders high quality glyphs directly
  14. *   into any RastPort.
  15. *
  16. *   FREETYPE2 BASED
  17. *
  18. *   The render engine of the library is based on FreeType2 project
  19. *   (http://www.freetype.org). This version of ttrender.library uses 2.0.9
  20. *   FreeType build.
  21. *
  22. *   REQUIREMENTS
  23. *
  24. *   The library requires at least CyberGraphX 3.x or Picasso96 2.x system. It
  25. *   is possible that non-antialiased output will be possible on AGA machines
  26. *   in the future.
  27. *
  28. *   FEATURES
  29. *
  30. *   The library expands FreeType functionality making usage of TrueType fonts
  31. *   easy and comfortable. Below you can find key features:
  32. *
  33. *   - renders whole strings (not single glyphs) with kerning.
  34. *   - antialiasing to any (not neccesarily uniform color) background.
  35. *   - system compatible output to any (including planar) RastPort.
  36. *   - supports JAM1. JAM2, INVERSVID, COMPLEMENT RastPort modes.
  37. *   - supports 8-bit to Unicode mapping with "ENV:ttfcodepage" table
  38. *     compatible with ttf.library.
  39. *   - allows for direct 16-bit Unicode string rendering.
  40. *   - easy to use, taglist based API.
  41. *   - efficient system-wide glyph cache system.
  42. *
  43. *   CACHE SYSTEM
  44. *
  45. *   The library uses my own (not that experimental FreeType one) cache system
  46. *   speeding up strings rendering alot. The cache is system-wide, it means it
  47. *   is common to every application using ttrender.library. Only used glyphs of
  48. *   given font face are cached. If the library encounters cache miss, missing
  49. *   glyph is loaded and rasterized on the fly. Cache system is totally
  50. *   transparent to the library user, so there are no cache functions in the
  51. *   library API. Cache uses one single Exec memory pool avoiding memory
  52. *   fragmentation.
  53. *
  54. *   FONT DIRECTORIES
  55. *
  56. *   The library searches for a font in three directories:
  57. *   1. Process current directory.
  58. *   2. "PROGDIR:" of the calling application.
  59. *   3. "FONTS:_TrueType_Outlines" as a common location for TrueType fonts.
  60. *
  61. *****************************************************************************
  62. *
  63. */
  64.  
  65. #define __NOLIBBASE__
  66.  
  67. #include <ft2build.h>
  68. #include FT_FREETYPE_H
  69.  
  70. #include <proto/exec.h>
  71. #include <proto/dos.h>
  72. #include <proto/expansion.h>
  73. #include <proto/utility.h>
  74. #include <proto/intuition.h>
  75. #include <proto/graphics.h>
  76. #include <proto/cybergraphics.h>
  77. #include <exec/libraries.h>
  78. #include <exec/resident.h>
  79. #include <exec/memory.h>
  80. #include <cybergraphx/cybergraphics.h>
  81. #include <string.h>
  82.  
  83. #define reg(a) __asm(#a)
  84. #define USELIB(a) struct Library *##a = ttb->ttb_##a
  85. #define MAX_PATH_LENGHT  1024       /* maximum length of file path including ending zero */
  86.  
  87. #include "lib.h"
  88.  
  89. struct TTRenderBase *Ttb;
  90. struct Library *__UtilityBase;    /* required for libnix 64-bit arithmetic */
  91.  
  92.  
  93. /*--- Functions prototypes -------------------------------------------------*/
  94.  
  95. struct TTRenderBase *LibInit(void *seglist reg(a0), struct Library *sysb reg(a6));
  96. struct TTRenderBase *LibOpen(struct TTRenderBase *ttb reg(a6));
  97. LONG LibClose(struct TTRenderBase *ttb reg(a6));
  98. APTR LibExpunge(struct TTRenderBase *ttb reg(a6));
  99. LONG LibReserved(void);
  100. BOOL TT_SetFont(struct TTRenderBase *ttb reg(a6), STRPTR name reg(a0), UWORD size reg(d0));
  101. BOOL TT_PutStr(struct TTRenderBase *ttb reg(a6), UBYTE *str reg(a0));
  102. BOOL TT_PutUStr(struct TTRenderBase *ttb reg(a6), UWORD *str reg(a0));
  103. BOOL TT_PutStrTagList(struct TTRenderBase *ttb reg(a6), UBYTE *str reg(a0), struct TagItem *taglist reg(a1));
  104. BOOL TT_PutUStrTagList(struct TTRenderBase *ttb reg(a6), UWORD *str reg(a0), struct TagItem *taglist reg(a1));
  105. ULONG TT_SetModesTagList(struct TTRenderBase *ttb reg(a6), struct TagItem *taglist reg(a0));
  106. ULONG TT_GetFontAttrsTagList(struct TTRenderBase *ttb reg(a6), struct TagItem *taglist reg(a0));
  107. ULONG TT_StrWidth(struct TTRenderBase *ttb reg(a6), UBYTE *string reg(a0));
  108. ULONG TT_UStrWidth(struct TTRenderBase *ttb reg(a6), UWORD *string reg(a0));
  109.  
  110. extern struct Resident romtag;
  111.  
  112. /* cached one glyph bitmap */
  113.  
  114. struct CachedBitmap
  115.   {
  116.     struct MinNode cb_Node;
  117.     LONG cb_AdvanceX;
  118.     LONG cb_AdvanceY;
  119.     WORD cb_OffsetX;
  120.     WORD cb_OffsetY;
  121.     FT_Bitmap cb_Bitmap;
  122.     ULONG cb_Index;
  123.   };
  124.  
  125. /* cached typeface of given size */
  126.  
  127. struct CachedSize
  128.   {
  129.     struct MinNode cs_Node;
  130.     UWORD cs_PixelSize;
  131.     struct MinList cs_Bitmaps;    /* list of CachedBitmap structures */
  132.   };
  133.  
  134. /* cached multiple sizes of one face */
  135.  
  136. struct CachedFont
  137.   {
  138.     struct MinNode cf_Node;
  139.     char *cf_Name;
  140.     struct MinList cf_Sizes;      /* list of CachedSize structures */
  141.   };
  142.  
  143. /* memory cache functions declarations */
  144.  
  145. struct CachedBitmap *cache_add_bitmap(struct TTRenderBase *ttb, struct CachedSize *cs,
  146.   FT_GlyphSlot glyph, ULONG index);
  147. struct CachedBitmap *cache_find_bitmap(struct TTRenderBase *ttb, struct CachedSize *cs,
  148.   ULONG index, char mode);
  149. void cache_flush_bitmap(struct TTRenderBase *ttb, struct CachedBitmap *cb);
  150.  
  151. struct CachedSize *cache_add_size(struct TTRenderBase *ttb, struct CachedFont *cf, UWORD size);
  152. struct CachedSize *cache_find_size(struct TTRenderBase *ttb, struct CachedFont *cf, UWORD size);
  153. void cache_flush_size(struct TTRenderBase *ttb, struct CachedSize *cs);
  154.  
  155. struct CachedFont *cache_add_font(struct TTRenderBase *ttb, char *name);
  156. struct CachedFont *cache_find_font(struct TTRenderBase *ttb, char *name);
  157. void cache_flush_font(struct TTRenderBase *ttb, struct CachedFont *cf);
  158.  
  159. void cache_flush_all(struct TTRenderBase *ttb);
  160.  
  161. /* codepage handling functions prototypes */
  162.  
  163. static void load_codepage(struct TTRenderBase *ttb);
  164. static void free_codepage(struct TTRenderBase *ttb);
  165.  
  166. /* === CODE STARTS HERE === */
  167.  
  168. /*--------------------------------------------------------------------------*/
  169.  
  170. static const void *FuncTable[] =
  171.  {
  172.   LibOpen,
  173.   LibClose,
  174.   LibExpunge,
  175.   LibReserved,
  176.   TT_PutStr,
  177.   TT_PutUStr,
  178.   TT_SetFont,
  179.   TT_PutStrTagList,
  180.   TT_PutUStrTagList,
  181.   TT_SetModesTagList,
  182.   TT_GetFontAttrsTagList,
  183.   TT_StrWidth,
  184.   TT_UStrWidth,
  185.   (APTR)-1
  186.  };
  187.  
  188.  
  189. /*----------------------------------------------------------------------------------------------------*/
  190.  
  191. static void get_rp_fgcolor(struct TTRenderBase *ttb, struct RastPort *rp, struct ColorMap *cm,
  192.  UBYTE *dest)
  193.   {
  194.     USELIB(GfxBase);
  195.  
  196.     ULONG tcolor[3];
  197.     WORD i;
  198.  
  199.     GetRGB32(cm, GetAPen(rp), 1, tcolor);
  200.     for (i = 0; i < 3; i++) dest[i] = tcolor[i] >> 24;
  201.   }
  202.  
  203. /*----------------------------------------------------------------------------------------------------*/
  204.  
  205. /*static void get_rp_bgcolor(struct TTRenderBase *ttb, struct RastPort *rp, struct ColorMap *cm,
  206.  UBYTE *dest)
  207.   {
  208.     USELIB(GfxBase);
  209.  
  210.     ULONG tcolor[3];
  211.     WORD i;
  212.  
  213.     GetRGB32(cm, GetBPen(rp), 1, tcolor);
  214.     for (i = 0; i < 3; i++) dest[i] = tcolor[i] >> 24;
  215.   }*/
  216.  
  217. /*----------------------------------------------------------------------------------------------------*/
  218.  
  219. static void blt_gray_bitmap(struct TTRenderBase *ttb, FT_Bitmap *bm, struct RastPort *rp,
  220.  struct ColorMap *cm, WORD dstx, WORD dsty)
  221.   {
  222.     USELIB(GfxBase);
  223.     USELIB(CyberGfxBase);
  224.     USELIB(SysBase);
  225.  
  226.     ULONG bufsize, drawmode;
  227.     UBYTE *buf;
  228.     UBYTE fgcolor[3], bgcolor[3];
  229.  
  230.     drawmode = GetDrMd(rp);
  231.     get_rp_fgcolor(ttb, rp, cm, fgcolor);
  232.  
  233.     bufsize = bm->width * bm->rows * sizeof(ULONG);
  234.  
  235.     if (buf = AllocPooled(ttb->ttb_MemPool, bufsize))
  236.       {
  237.         WORD xi, yi;
  238.         UBYTE *ptr = buf, *src = bm->buffer;
  239.  
  240.         ReadPixelArray(buf, 0, 0, bm->width * sizeof(ULONG), rp, dstx, dsty, bm->width, bm->rows,
  241.           RECTFMT_ARGB);
  242.  
  243.         for (yi = 0; yi < bm->rows; yi++)
  244.           {
  245.             for (xi = 0; xi < bm->width; xi++)
  246.               {
  247.                 UBYTE alpha;
  248.  
  249.                 *ptr++ = 0;
  250.                 alpha = (drawmode & INVERSVID) ? ~src[xi] : src[xi];
  251.  
  252.                 *ptr += ((WORD)(fgcolor[0] - *ptr++) * (WORD)(alpha)) >> 8;
  253.                 *ptr += ((WORD)(fgcolor[1] - *ptr++) * (WORD)(alpha)) >> 8;
  254.                 *ptr += ((WORD)(fgcolor[2] - *ptr++) * (WORD)(alpha)) >> 8;
  255.               }
  256.             src += bm->pitch;
  257.           }
  258.  
  259.         WritePixelArray(buf, 0, 0, bm->width * sizeof(ULONG), rp, dstx, dsty, bm->width, bm->rows,
  260.          RECTFMT_ARGB);
  261.  
  262.         FreePooled(ttb->ttb_MemPool, buf, bufsize);
  263.       }
  264.   }
  265.  
  266.  
  267. /*----------------------------------------------------------------------------------------------------*/
  268.  
  269. static void blt_mono_bitmap(struct TTRenderBase *ttb, FT_Bitmap *bm, struct RastPort *rp,
  270.  struct ColorMap *cm, WORD dstx, WORD dsty)
  271.   {
  272.     USELIB(GfxBase);
  273.     USELIB(CyberGfxBase);
  274.     USELIB(SysBase);
  275.  
  276.     ULONG bufsize, drawmode;
  277.     UBYTE *buf;
  278.     UBYTE fgcolor[3], bgcolor[3];
  279.  
  280.     drawmode = GetDrMd(rp);
  281.     get_rp_fgcolor(ttb, rp, cm, fgcolor);
  282.  
  283.     bufsize = bm->width * bm->rows * sizeof(ULONG);
  284.  
  285.     if (buf = AllocPooled(ttb->ttb_MemPool, bufsize))
  286.       {
  287.         WORD xi, yi;
  288.         UBYTE *ptr = buf, *src = bm->buffer;
  289.  
  290.         ReadPixelArray(buf, 0, 0, bm->width * sizeof(ULONG), rp, dstx, dsty, bm->width, bm->rows,
  291.           RECTFMT_ARGB);
  292.  
  293.         for (yi = 0; yi < bm->rows; yi++)
  294.           {
  295.             for (xi = 0; xi < bm->width; xi++)
  296.               {
  297.                 UBYTE b, mask;
  298.  
  299.                 if (!(xi & 7))
  300.                   {
  301.                     mask = 0x80;
  302.                     b = src[xi >> 3];
  303.                   }
  304.                 else mask >>= 1;
  305.  
  306.                 *ptr++ = 0;
  307.                 if (b & mask)
  308.                   {
  309.                     *ptr++ = fgcolor[0];
  310.                     *ptr++ = fgcolor[1];
  311.                     *ptr++ = fgcolor[2];
  312.                   }
  313.                 else ptr += 3;
  314.               }
  315.             src += bm->pitch;
  316.           }
  317.  
  318.         WritePixelArray(buf, 0, 0, bm->width * sizeof(ULONG), rp, dstx, dsty, bm->width, bm->rows,
  319.          RECTFMT_ARGB);
  320.  
  321.         FreePooled(ttb->ttb_MemPool, buf, bufsize);
  322.       }
  323.   }
  324.  
  325. /*----------------------------------------------------------------------------------------------------*/
  326.  
  327. ULONG tt_strwidth(struct TTRenderBase *ttb, struct RenderEnv *re, APTR str, BOOL unicode)
  328.   {
  329.     USELIB(DOSBase);
  330.  
  331.     ULONG chindex = 0, previous;
  332.     ULONG xpos = 0, ypos = 0;
  333.     int error;
  334.     UBYTE *nstr = str;
  335.     UWORD *ustr = str;
  336.     UWORD chcode;
  337.     struct CachedBitmap *cb;
  338.     FT_Face face = ttb->ttb_Face;
  339.     BOOL use_kerning = FT_HAS_KERNING(face);
  340.  
  341.     struct RastPort *rp = re->re_TargetRPort;
  342.     struct ColorMap *cm = re->re_TargetCMap;
  343.     char render_mode = re->re_Antialias ? 0 : ft_render_mode_mono;
  344.     char bitmap_mode = re->re_Antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
  345.  
  346.     while (chcode = unicode ? *ustr++ : *nstr++)
  347.       {
  348.         previous = chindex;
  349.         if (!unicode && ttb->ttb_CodePage) chcode = ttb->ttb_CodePage[chcode];
  350.  
  351.         chindex = FT_Get_Char_Index(face, chcode);
  352.  
  353.  
  354.         if (previous && use_kerning)
  355.           {
  356.             FT_Vector delta;
  357.  
  358.             FT_Get_Kerning(face, previous, chindex, ft_kerning_unfitted, &delta);
  359.             xpos += delta.x;
  360.           }
  361.  
  362.         if (cb = cache_find_bitmap(ttb->ttb_RealTTRenderBase, ttb->ttb_CurrentCache,
  363.           chindex, bitmap_mode))
  364.           {
  365.             DBG("MemCache HIT");
  366.  
  367.             xpos += cb->cb_AdvanceX;
  368.             ypos += cb->cb_AdvanceY;
  369.           }
  370.         else
  371.           {
  372.             DBG("MemCache MISS");
  373.  
  374.             if (!FT_Load_Glyph(face, chindex, 0))
  375.               {
  376.                 if (!(error = FT_Render_Glyph(face->glyph, render_mode)))
  377.                   {
  378.                     FT_Bitmap *bm = &(face->glyph->bitmap);
  379.  
  380.                     cache_add_bitmap(ttb->ttb_RealTTRenderBase, ttb->ttb_CurrentCache,
  381.                       face->glyph, chindex);
  382.                   }
  383.               }
  384.             xpos += face->glyph->advance.x;
  385.             ypos += face->glyph->advance.y;
  386.           }
  387.       }
  388.     return ((xpos + 32) >> 6);
  389.   }
  390.  
  391.  
  392. void tt_putstr(struct TTRenderBase *ttb, struct RenderEnv *re, WORD x, WORD y,
  393.  APTR str, BOOL unicode)
  394.   {
  395.     USELIB_DBG(DOSBase)
  396. //    USELIB(DOSBase);
  397.     USELIB(GfxBase);
  398.  
  399.     ULONG chindex = 0, previous;
  400.     ULONG xpos = x << 6, ypos = y << 6;
  401.     int error;
  402.     UBYTE *nstr = str;
  403.     UWORD *ustr = str;
  404.     UWORD chcode;
  405.     struct CachedBitmap *cb;
  406.     FT_Face face = ttb->ttb_Face;
  407.     BOOL use_kerning = FT_HAS_KERNING(face);
  408.     UWORD pixlen;
  409.  
  410.     struct RastPort *rp = re->re_TargetRPort;
  411.     struct ColorMap *cm = re->re_TargetCMap;
  412.     char render_mode = re->re_Antialias ? 0 : ft_render_mode_mono;
  413.     char bitmap_mode = re->re_Antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
  414.  
  415.     pixlen = tt_strwidth(ttb, re, str, unicode);
  416.  
  417.     /* draw backgorund in JAM2 mode */
  418.  
  419.     if (GetDrMd(rp) & JAM2)
  420.       {
  421.         ULONG old_fg_pen = GetAPen(rp);
  422.  
  423.         SetAPen(rp, GetBPen(rp));
  424.         RectFill(rp, rp->cp_x, rp->cp_y - ttb->ttb_Ascender, rp->cp_x + pixlen,
  425.          rp->cp_y + ttb->ttb_Descender);
  426.         SetAPen(rp, old_fg_pen);
  427.       }
  428.  
  429.     while (chcode = unicode ? *ustr++ : *nstr++)
  430.       {
  431.         previous = chindex;
  432.         if (!unicode && ttb->ttb_CodePage) chcode = ttb->ttb_CodePage[chcode];
  433.  
  434.         chindex = FT_Get_Char_Index(face, chcode);
  435.  
  436.  
  437.         if (previous && use_kerning)
  438.           {
  439.             FT_Vector delta;
  440.  
  441.             FT_Get_Kerning(face, previous, chindex, ft_kerning_unfitted, &delta);
  442.             xpos += delta.x;
  443.           }
  444.  
  445.         /* glyph already cached with tt_strwidth() */
  446.  
  447.         cb = cache_find_bitmap(ttb->ttb_RealTTRenderBase, ttb->ttb_CurrentCache,
  448.           chindex, bitmap_mode);
  449.  
  450.         switch (cb->cb_Bitmap.pixel_mode)
  451.           {
  452.             case ft_pixel_mode_grays:
  453.               blt_gray_bitmap(ttb, &cb->cb_Bitmap, rp, cm, (xpos >> 6) + cb->cb_OffsetX,
  454.                (ypos >> 6) - cb->cb_OffsetY);
  455.             break;
  456.  
  457.             case ft_pixel_mode_mono:
  458.               blt_mono_bitmap(ttb, &cb->cb_Bitmap, rp, cm, (xpos >> 6) + cb->cb_OffsetX,
  459.                (ypos >> 6) - cb->cb_OffsetY);
  460.             break;
  461.           }
  462.         xpos += cb->cb_AdvanceX;
  463.         ypos += cb->cb_AdvanceY;
  464.       }
  465.   }
  466.  
  467. /*----------------------------------------------------------------------------------------------------*/
  468. /* always gets "real" TTRenderBase */
  469.  
  470. struct CachedBitmap *cache_add_bitmap(struct TTRenderBase *ttb, struct CachedSize *cs,
  471.   FT_GlyphSlot glyph, ULONG index)
  472.   {
  473.     USELIB(SysBase);
  474.     USELIB_DBG(DOSBase)
  475.  
  476.     struct CachedBitmap *cb;
  477.     ULONG bmsize;
  478.  
  479.     if (cb = AllocPooled(ttb->ttb_MemPool, sizeof(struct CachedBitmap)))
  480.       {
  481.         cb->cb_Index = index;
  482.         cb->cb_AdvanceX = glyph->advance.x;
  483.         cb->cb_AdvanceY = glyph->advance.y;
  484.         cb->cb_OffsetX = glyph->bitmap_left;
  485.         cb->cb_OffsetY = glyph->bitmap_top;
  486.         CopyMem(&glyph->bitmap, &cb->cb_Bitmap, sizeof(FT_Bitmap));
  487.         bmsize = cb->cb_Bitmap.rows * cb->cb_Bitmap.pitch;
  488.  
  489.         if (bmsize)
  490.           {
  491.             if (cb->cb_Bitmap.buffer = AllocPooled(ttb->ttb_MemPool, bmsize))
  492.               {
  493.                 CopyMem(glyph->bitmap.buffer, cb->cb_Bitmap.buffer, bmsize);
  494.               }
  495.           }
  496.         else cb->cb_Bitmap.buffer = NULL;
  497.  
  498.         if (cb->cb_Bitmap.buffer || !bmsize)
  499.           {
  500.             ttb->ttb_MemCacheSize += sizeof(struct CachedBitmap) + bmsize;
  501.             AddTail((struct List*)&cs->cs_Bitmaps, (struct Node*)cb);
  502.  
  503.             DBG2("\tMemCache: %ld glyph added, cache size %ld bytes.", cb->cb_Index,
  504.               ttb->ttb_MemCacheSize);
  505.             return cb;
  506.           }
  507.         FreePooled(ttb->ttb_MemPool, cb, sizeof(struct CachedBitmap));
  508.       }
  509.     return NULL;
  510.   }
  511.  
  512. /*----------------------------------------------------------------------------------------------------*/
  513. /* always gets "real" TTRenderBase */
  514.  
  515. struct CachedBitmap *cache_find_bitmap(struct TTRenderBase *ttb, struct CachedSize *cs, ULONG index,
  516.   char mode)
  517.   {
  518.     struct MinNode *n;
  519.  
  520.     for(n = cs->cs_Bitmaps.mlh_Head; n->mln_Succ; n = n->mln_Succ)
  521.       {
  522.         if (((struct CachedBitmap*)n)->cb_Index == index &&
  523.          ((struct CachedBitmap*)n)->cb_Bitmap.pixel_mode == mode) return (struct CachedBitmap*)n;
  524.       }
  525.     return NULL;
  526.   }
  527.  
  528. /*----------------------------------------------------------------------------------------------------*/
  529. /* always gets "real" TTRenderBase */
  530.  
  531. void cache_flush_bitmap(struct TTRenderBase *ttb, struct CachedBitmap *cb)
  532.   {
  533.     USELIB(SysBase);
  534.     USELIB_DBG(DOSBase)
  535.     ULONG bsize;
  536.  
  537.     DBG1("\t\tMemCache: '%ld' bitmap flushed.", cb->cb_Index);
  538.  
  539.     bsize = cb->cb_Bitmap.rows * cb->cb_Bitmap.pitch;
  540.     Remove((struct Node*)cb);
  541.  
  542.     if (cb->cb_Bitmap.buffer) FreePooled(ttb->ttb_MemPool, cb->cb_Bitmap.buffer, bsize);
  543.     FreePooled(ttb->ttb_MemPool, cb, sizeof(struct CachedBitmap));
  544.     ttb->ttb_MemCacheSize -= sizeof(struct CachedBitmap) + bsize;
  545.  
  546.     DBG1("\t\tCache size %ld bytes.",  ttb->ttb_MemCacheSize);
  547.   }
  548.  
  549. /*----------------------------------------------------------------------------------------------------*/
  550. /* always gets "real" TTRenderBase */
  551.  
  552. struct CachedSize *cache_add_size(struct TTRenderBase *ttb, struct CachedFont *cf, UWORD size)
  553.   {
  554.     USELIB(SysBase);
  555.     USELIB_DBG(DOSBase)
  556.  
  557.     struct CachedSize *cs;
  558.  
  559.     if (cs = AllocPooled(ttb->ttb_MemPool, sizeof(struct CachedSize)))
  560.       {
  561.         cs->cs_PixelSize = size;
  562.         cs->cs_Bitmaps.mlh_Head = (struct MinNode*)&cs->cs_Bitmaps.mlh_Tail;
  563.         cs->cs_Bitmaps.mlh_Tail = NULL;
  564.         cs->cs_Bitmaps.mlh_TailPred = (struct MinNode*)&cs->cs_Bitmaps.mlh_Head;
  565.         ttb->ttb_MemCacheSize += sizeof(struct CachedSize);
  566.         AddTail((struct List*)&cf->cf_Sizes, (struct Node*)cs);
  567.  
  568.         DBG2("\tMemCache: %ld size added, cache size %ld bytes.", cs->cs_PixelSize,
  569.           ttb->ttb_MemCacheSize);
  570.         return cs;
  571.       }
  572.     return NULL;
  573.   }
  574.  
  575. /*----------------------------------------------------------------------------------------------------*/
  576. /* always gets "real" TTRenderBase */
  577.  
  578. struct CachedSize *cache_find_size(struct TTRenderBase *ttb, struct CachedFont *cf, UWORD size)
  579.   {
  580.     struct MinNode *n;
  581.  
  582.     for(n = cf->cf_Sizes.mlh_Head; n->mln_Succ; n = n->mln_Succ)
  583.       {
  584.         if (((struct CachedSize*)n)->cs_PixelSize == size) return (struct CachedSize*)n;
  585.       }
  586.     return NULL;
  587.   }
  588.  
  589. /*----------------------------------------------------------------------------------------------------*/
  590. /* always gets "real" TTRenderBase */
  591.  
  592. void cache_flush_size(struct TTRenderBase *ttb, struct CachedSize *cs)
  593.   {
  594.     USELIB(SysBase);
  595.     USELIB_DBG(DOSBase)
  596.  
  597.     struct MinNode *n, *n2;
  598.  
  599.     DBG1("\tMemCache: '%ld' size flushed.", cs->cs_PixelSize);
  600.  
  601.     Remove((struct Node*)cs);
  602.  
  603.     n = cs->cs_Bitmaps.mlh_Head;
  604.     while(n2 = n->mln_Succ)
  605.       {
  606.         cache_flush_bitmap(ttb, (struct CachedBitmap*)n);
  607.         n = n2;
  608.       }
  609.  
  610.     FreePooled(ttb->ttb_MemPool, cs, sizeof(struct CachedSize));
  611.     ttb->ttb_MemCacheSize -= sizeof(struct CachedSize);
  612.  
  613.     DBG1("\tCache size %ld bytes.",  ttb->ttb_MemCacheSize);
  614.   }
  615.  
  616. /*----------------------------------------------------------------------------------------------------*/
  617. /* always gets "real" TTRenderBase */
  618.  
  619. struct CachedFont *cache_add_font(struct TTRenderBase *ttb, char *name)
  620.   {
  621.     USELIB(SysBase);
  622.     USELIB_DBG(DOSBase)
  623.  
  624.     struct CachedFont *cf;
  625.     ULONG namelen;
  626.  
  627.     namelen = strlen(name) + 1;
  628.  
  629.     if (cf = AllocPooled(ttb->ttb_MemPool, sizeof(struct CachedFont)))
  630.       {
  631.         if (cf->cf_Name = AllocPooled(ttb->ttb_MemPool, namelen))
  632.           {
  633.             strcpy(cf->cf_Name, name);
  634.             cf->cf_Sizes.mlh_Head = (struct MinNode*)&cf->cf_Sizes.mlh_Tail;
  635.             cf->cf_Sizes.mlh_Tail = NULL;
  636.             cf->cf_Sizes.mlh_TailPred = (struct MinNode*)&cf->cf_Sizes.mlh_Head;
  637.             ttb->ttb_MemCacheSize += sizeof(struct CachedFont) + namelen;
  638.             AddTail((struct List*)&ttb->ttb_MemoryCache, (struct Node*)cf);
  639.  
  640.             DBG2("\tMemCache: '%s' font added, cache size %ld bytes.", (LONG)cf->cf_Name,
  641.               ttb->ttb_MemCacheSize);
  642.             return cf;
  643.           }
  644.         FreePooled(ttb->ttb_MemPool, cf, sizeof(struct CachedFont));
  645.       }
  646.     return NULL;
  647.   }
  648.  
  649. /*----------------------------------------------------------------------------------------------------*/
  650. /* always gets "real" TTRenderBase */
  651.  
  652. void cache_flush_font(struct TTRenderBase *ttb, struct CachedFont *cf)
  653.   {
  654.     USELIB(SysBase);
  655.     USELIB_DBG(DOSBase)
  656.  
  657.     struct MinNode *n, *n2;
  658.     ULONG namelen;
  659.  
  660.     namelen = strlen(cf->cf_Name) + 1;
  661.  
  662.     DBG1("\tMemCache: '%s' font flushed.", (LONG)cf->cf_Name);
  663.  
  664.     Remove((struct Node*)cf);
  665.  
  666.     n = cf->cf_Sizes.mlh_Head;
  667.     while(n2 = n->mln_Succ)
  668.       {
  669.         cache_flush_size(ttb, (struct CachedSize*)n);
  670.         n = n2;
  671.       }
  672.  
  673.     FreePooled(ttb->ttb_MemPool, cf->cf_Name, namelen);
  674.     FreePooled(ttb->ttb_MemPool, cf, sizeof(struct CachedFont));
  675.     ttb->ttb_MemCacheSize -= namelen + sizeof(struct CachedFont);
  676.  
  677.     DBG1("\tCache size %ld bytes.",  ttb->ttb_MemCacheSize);
  678.   }
  679.  
  680. /*----------------------------------------------------------------------------------------------------*/
  681. /* always gets "real" TTRenderBase */
  682.  
  683. struct CachedFont *cache_find_font(struct TTRenderBase *ttb, char *name)
  684.   {
  685.     struct MinNode *n;
  686.  
  687.     for(n = ttb->ttb_MemoryCache.mlh_Head; n->mln_Succ; n = n->mln_Succ)
  688.       {
  689.         if (strcmp(((struct CachedFont*)n)->cf_Name, name) == 0) return (struct CachedFont*)n;
  690.       }
  691.     return NULL;
  692.   }
  693.  
  694. /*----------------------------------------------------------------------------------------------------*/
  695. /* always gets "real" TTRenderBase */
  696.  
  697. void cache_flush_all(struct TTRenderBase *ttb)
  698.   {
  699.     struct MinNode *n, *n2;
  700.  
  701.     n = ttb->ttb_MemoryCache.mlh_Head;
  702.     while(n2 = n->mln_Succ)
  703.       {
  704.         cache_flush_font(ttb, (struct CachedFont*)n);
  705.         n = n2;
  706.       }
  707.   }
  708.  
  709. /*----------------------------------------------------------------------------------------------------*/
  710.  
  711. static void load_codepage(struct TTRenderBase *ttb)
  712.   {
  713.     struct Library *SysBase = ttb->ttb_SysBase;
  714.     struct Library *DOSBase = ttb->ttb_DOSBase;
  715.     BPTR codepage;
  716.     int d;
  717.  
  718.     /* load codepage */
  719.  
  720.     ttb->ttb_CodePage = NULL;
  721.  
  722.     if (codepage = Open("ENV:ttfcodepage", MODE_OLDFILE))
  723.       {
  724.         if (ttb->ttb_CodePage = AllocPooled(ttb->ttb_MemPool, 512))
  725.           {
  726.             if (Read(codepage, ttb->ttb_CodePage, 512) != 512)
  727.               {
  728.                  FreePooled(ttb->ttb_MemPool, ttb->ttb_CodePage, 512);
  729.                  ttb->ttb_CodePage = NULL;
  730.               }
  731.           }
  732.         Close(codepage);
  733.       }
  734.   }
  735.  
  736. /*----------------------------------------------------------------------------------------------------*/
  737.  
  738. static void free_codepage(struct TTRenderBase *ttb)
  739.   {
  740.     USELIB(SysBase);
  741.  
  742.     if (ttb->ttb_CodePage) FreePooled(ttb->ttb_MemPool, ttb->ttb_CodePage, 512);
  743.   }
  744.  
  745. /*-------------------------------------------------------------------------*/
  746. /* INIT                                                                    */
  747. /*-------------------------------------------------------------------------*/
  748.  
  749. __saveds struct TTRenderBase *LibInit (APTR seglist reg(a0),
  750.  struct Library *sysb reg(a6))
  751.  {
  752.   struct TTRenderBase *ttb, *rval = NULL;
  753.   struct Library *SysBase = sysb;
  754.  
  755.   if (ttb = (struct TTRenderBase*)MakeLibrary (FuncTable, NULL, NULL,
  756.    sizeof (struct TTRenderBase), 0))
  757.    {
  758.     ttb->ttb_Lib.lib_Node.ln_Type = NT_LIBRARY;
  759.     ttb->ttb_Lib.lib_Node.ln_Name = romtag.rt_Name;
  760.     ttb->ttb_Lib.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
  761.     ttb->ttb_Lib.lib_Version = 2;
  762.     ttb->ttb_Lib.lib_Revision = 0;
  763.     ttb->ttb_Lib.lib_IdString = romtag.rt_IdString;
  764.     ttb->ttb_Lib.lib_OpenCnt = 0;
  765.     ttb->ttb_SegList = seglist;
  766.     ttb->ttb_SysBase = SysBase;
  767.     ttb->ttb_MemPool = NULL;
  768.     ttb->ttb_RealTTRenderBase = NULL;
  769.     ttb->ttb_RenderEnv.re_TargetRPort = NULL;
  770.     ttb->ttb_RenderEnv.re_TargetCMap = NULL;
  771.     ttb->ttb_RenderEnv.re_Antialias = FALSE;
  772.     ttb->ttb_GfxBase = NULL;
  773.     ttb->ttb_DOSBase = NULL;
  774.     ttb->ttb_CyberGfxBase = NULL;
  775.     ttb->ttb_UtilityBase = NULL;
  776.     ttb->ttb_FTLib = NULL;
  777.     ttb->ttb_Face = NULL;
  778.     ttb->ttb_MemoryCache.mlh_Head = (struct MinNode*)&ttb->ttb_MemoryCache.mlh_Tail;
  779.     ttb->ttb_MemoryCache.mlh_Tail = NULL;
  780.     ttb->ttb_MemoryCache.mlh_TailPred = (struct MinNode*)&ttb->ttb_MemoryCache.mlh_Head;
  781.     ttb->ttb_MemCacheSize = 0;
  782.     ttb->ttb_Ascender = 0;
  783.     ttb->ttb_Descender = 0;
  784.     AddLibrary ((struct Library*)ttb);
  785.     rval = ttb;
  786.    }
  787.   return rval;
  788.  }
  789.  
  790.  
  791. /*-------------------------------------------------------------------------*/
  792. /* OPEN                                                                    */
  793. /*-------------------------------------------------------------------------*/
  794.  
  795. static struct TTRenderBase *init_resources(struct TTRenderBase *ttb)
  796.   {
  797.     USELIB(SysBase);
  798.     USELIB_DBG(DOSBase)
  799.     LONG ft_error;
  800.  
  801.     if (!(__UtilityBase = OpenLibrary("utility.library", 39))) return NULL;
  802.     ttb->ttb_UtilityBase = __UtilityBase;
  803.     if (!(ttb->ttb_GfxBase = OpenLibrary("graphics.library", 39))) return NULL;
  804.     if (!(ttb->ttb_DOSBase = OpenLibrary("dos.library", 38))) return NULL;
  805.     if (!(ttb->ttb_CyberGfxBase = OpenLibrary("cybergraphics.library", 41))) return NULL;
  806.     if (!(ttb->ttb_MemPool = CreatePool(MEMF_ANY | MEMF_CLEAR, 1024, 512))) return NULL;
  807.  
  808.     #ifdef TTR_DEBUG
  809.     DOSBase = ttb->ttb_DOSBase;
  810.     ttb->debug = Open("KCON:0/17/640/150/ttrender.library/AUTO/CLOSE", MODE_NEWFILE);
  811.     #endif
  812.  
  813.     load_codepage(ttb);
  814.  
  815.     Ttb = ttb;
  816.  
  817.     if (ft_error = FT_Init_FreeType(&ttb->ttb_FTLib) != 0)
  818.       {
  819.         DBG1("FT_Init_FreeType() failed, error %ld.", ft_error);
  820.         ttb->ttb_FTLib = NULL;
  821.         return NULL;
  822.       }
  823.     DBG("Library initialization successfull.");
  824.     return ttb;
  825.   }
  826.  
  827.  
  828. /* always gets "real" TTRenderBase */
  829.  
  830. static void free_resources(struct TTRenderBase *ttb)
  831.   {
  832.     USELIB(SysBase);
  833.  
  834.     if (ttb->ttb_FTLib) FT_Done_FreeType(ttb->ttb_FTLib);
  835.     if (ttb->ttb_CyberGfxBase) CloseLibrary(ttb->ttb_CyberGfxBase);
  836.     if (ttb->ttb_DOSBase) CloseLibrary(ttb->ttb_DOSBase);
  837.     if (ttb->ttb_GfxBase) CloseLibrary(ttb->ttb_GfxBase);
  838.     if (__UtilityBase) CloseLibrary(__UtilityBase);
  839.     cache_flush_all(ttb);
  840.     free_codepage(ttb);
  841.     if (ttb->ttb_MemPool) DeletePool(ttb->ttb_MemPool);
  842.     return;
  843.   }
  844.  
  845.  
  846. __saveds struct TTRenderBase *LibOpen (struct TTRenderBase *ttb_real reg(a6))
  847.   {
  848.     struct TTRenderBase *ttb_fake = NULL;
  849.     struct Library *SysBase = ttb_real->ttb_SysBase;
  850.  
  851.     if (ttb_fake = (struct TTRenderBase*)MakeLibrary (FuncTable, NULL, NULL,
  852.       sizeof (struct TTRenderBase), 0))
  853.       {
  854.         if (!ttb_real->ttb_MemPool)
  855.           {
  856.             if (!init_resources(ttb_real))
  857.               {
  858.                 free_resources(ttb_real);
  859.                 FreeMem ((APTR)ttb_fake - ttb_fake->ttb_Lib.lib_NegSize,
  860.                   (LONG)ttb_fake->ttb_Lib.lib_PosSize + (LONG)ttb_fake->ttb_Lib.lib_NegSize);
  861.                 return NULL;
  862.               }
  863.           }
  864.  
  865.         CopyMem((APTR)ttb_real, (APTR)ttb_fake, sizeof(struct TTRenderBase));
  866.         ttb_fake->ttb_RealTTRenderBase = ttb_real;
  867.           {
  868.             #ifdef TTR_DEBUG
  869.             struct Library *DOSBase = ttb_fake->ttb_DOSBase;
  870.             #endif
  871.  
  872.             DBG2("Library opened, real base $%08lx, priv base $%08lx.", (LONG)ttb_real, (LONG)ttb_fake);
  873.           }
  874.         ttb_real->ttb_Lib.lib_OpenCnt++;
  875.         ttb_real->ttb_Lib.lib_Flags &= ~LIBF_DELEXP;
  876.         return ttb_fake;
  877.       }
  878.   }
  879.  
  880. /*-------------------------------------------------------------------------*/
  881. /* CLOSE                                                                   */
  882. /*-------------------------------------------------------------------------*/
  883.  
  884. __saveds long LibClose(struct TTRenderBase *ttb_fake reg(a6))
  885.   {
  886.     struct Library *SysBase = ttb_fake->ttb_SysBase;
  887.     struct TTRenderBase *ttb_real = ttb_fake->ttb_RealTTRenderBase;
  888.  
  889.     #ifdef TTR_DEBUG
  890.     struct Library *DOSBase = ttb_fake->ttb_DOSBase;
  891.     #endif
  892.  
  893.     if (ttb_fake->ttb_Face) FT_Done_Face(ttb_fake->ttb_Face);
  894.     FreeMem ((APTR)ttb_fake - ttb_fake->ttb_Lib.lib_NegSize,
  895.       (LONG)ttb_fake->ttb_Lib.lib_PosSize + (LONG)ttb_fake->ttb_Lib.lib_NegSize);
  896.  
  897.     DBG("Library closed");
  898.     if (!(--ttb_real->ttb_Lib.lib_OpenCnt))
  899.       {
  900.         if (ttb_real->ttb_Lib.lib_Flags & LIBF_DELEXP) return ((long)LibExpunge(ttb_real));
  901.       }
  902.     return 0;
  903.   }
  904.  
  905. /*-------------------------------------------------------------------------*/
  906. /* EXPUNGE                                                                 */
  907. /*-------------------------------------------------------------------------*/
  908.  
  909. __saveds APTR LibExpunge (struct TTRenderBase *ttb reg(a6))
  910.   {
  911.     USELIB(SysBase);
  912.     APTR seglist;
  913.  
  914.     if (ttb->ttb_Lib.lib_OpenCnt)
  915.       {
  916.         ttb->ttb_Lib.lib_Flags |= LIBF_DELEXP;
  917.         return 0;
  918.       }
  919.     Remove ((struct Node*)ttb);
  920.     free_resources(ttb);
  921.     seglist = ttb->ttb_SegList;
  922.     FreeMem ((APTR)ttb - ttb->ttb_Lib.lib_NegSize, (LONG)ttb->ttb_Lib.lib_PosSize +
  923.       (LONG)ttb->ttb_Lib.lib_NegSize);
  924.     return seglist;
  925.   }
  926.  
  927. /*-------------------------------------------------------------------------*/
  928. /* RESERVED                                                                */
  929. /*-------------------------------------------------------------------------*/
  930.  
  931. long LibReserved (void)
  932.   {
  933.     return 0;
  934.   }
  935.  
  936.  
  937. /****** ttrender.library/TT_SetFont *****************************************
  938. *
  939. *   NAME
  940. *       TT_SetFont -- Opens TrueType font with given name and size.
  941. *
  942. *   SYNOPSIS
  943. *       success = TT_SetFont (name, size)
  944. *                             A0    D0:16
  945. *
  946. *       BOOL TT_SetFont (STRPTR, UWORD);
  947. *
  948. *   FUNCTION
  949. *       Opens TrueType font file and sets current font size in pixels. Every
  950. *       following call to TT_PutStr[Tags/TagList]() or
  951. *       TT_PutUStr[Tags/TagList]() will use this font and size.
  952. *
  953. *   INPUTS
  954. *       name - pointer to a NULL terminated string containing font name.
  955. *              ".ttf" suffix will be added automatically. Search order is
  956. *              defined as follows:
  957. *              1. current directory
  958. *                  "<name>.ttf"
  959. *              2. PROGDIR:
  960. *                  "PROGDIR:<name>.ttf"
  961. *              3. "FONTS:_TrueType_Outlines" (by analogy to _Bullet_Outlines)
  962. *                  "FONTS:_TrueType_Outlines/<name>.ttf"
  963. *       size - screen size of the font in pixels (to be exact - it is the
  964. *              distance between baselines of two following lines of text
  965. *              expressed in pixels).
  966. *
  967. *   RESULT
  968. *       success - TRUE if the font has been opened successfully, FALSE
  969. *                 otherwise. This function can fail for three reasons:
  970. *                 1. File not found or malformed.
  971. *                 2. Zero font size.
  972. *                 3. No memory for requested (too big?) size.
  973. *
  974. *   NOTES
  975. *
  976. *   BUGS
  977. *
  978. *   SEE ALSO
  979. *       TT_PutStr(), TT_PutUStr()
  980. *
  981. *****************************************************************************
  982. *
  983. */
  984.  
  985. __saveds BOOL TT_SetFont(struct TTRenderBase *ttb reg(a6), STRPTR name reg(a0), UWORD size reg(d0))
  986.   {
  987.     USELIB(SysBase);
  988.     USELIB(DOSBase);
  989.  
  990.     STRPTR filepath;
  991.     BOOL result = FALSE;
  992.     BPTR testlock = 0;
  993.     LONG error;
  994.  
  995.     struct CachedSize *cs;
  996.     struct CachedFont *cf;
  997.     struct RenderEnv *re = &ttb->ttb_RenderEnv;
  998.  
  999.     DBG2("TT_SetFont(\"%s\", %ld):", name, size);
  1000.  
  1001.     if (ttb->ttb_Face)
  1002.       {
  1003.         FT_Done_Face(ttb->ttb_Face);
  1004.         ttb->ttb_Face = NULL;
  1005.       }
  1006.  
  1007.     DBG("\tOld typeface cleared.");
  1008.  
  1009.     /* add .ttf suffix */
  1010.  
  1011.     if (filepath = AllocPooled(ttb->ttb_MemPool, MAX_PATH_LENGHT))
  1012.       {
  1013.         STRPTR p, q;
  1014.  
  1015.         strncpy(filepath, name, MAX_PATH_LENGHT - 8);
  1016.         strcat(filepath, ".ttf");
  1017.  
  1018.         /* OK, we have a full name, let's try current directory */
  1019.  
  1020.         DBG1("\tFont search: searching for \"%s\" file...", filepath);
  1021.  
  1022.         if (!(testlock = Lock(filepath, ACCESS_READ)))
  1023.           {
  1024.             /* Try "PROGDIR:" now */
  1025.  
  1026.             strcpy(filepath, "PROGDIR:");
  1027.             AddPart(filepath, name, MAX_PATH_LENGHT - 16);
  1028.             strcat(filepath, ".ttf");
  1029.             DBG1("\tFont search: searching for \"%s\" file...", filepath);
  1030.             if (!(testlock = Lock(filepath, ACCESS_READ)))
  1031.               {
  1032.                 /* Still not found, try "FONTS:_TrueType_Outlines/" */
  1033.  
  1034.                 strcpy(filepath, "FONTS:_TrueType_Outlines/");
  1035.                 AddPart(filepath, name, MAX_PATH_LENGHT - 32);
  1036.                 strcat(filepath, ".ttf");
  1037.                 DBG1("\tFont search: searching for \"%s\" file...", filepath);
  1038.                 if (!(testlock = Lock(filepath, ACCESS_READ)))
  1039.                   {
  1040.                     DBG("\tFont search: file not found.");
  1041.                     result = FALSE;
  1042.                   }
  1043.               }
  1044.           }
  1045.  
  1046.         if (testlock)
  1047.           {
  1048.             /* font file found, Tank, load us up :-) */
  1049.  
  1050.             DBG("\tFont file found, loading...");
  1051.             DBG1("\tFTLib = $%08lx.", ttb->ttb_FTLib);
  1052.             if (!(error = FT_New_Face(ttb->ttb_FTLib, filepath, 0, &ttb->ttb_Face)))
  1053.               {
  1054.                 ULONG px_size, asc, desc;
  1055.  
  1056.                 DBG1("\tFont face \"%s\" loaded succesfully.", name);
  1057.  
  1058.                 /* compute correct pixel size for given height */
  1059.  
  1060.                 px_size = ((size << 17) + (ttb->ttb_Face->height >> 1)) / ttb->ttb_Face->height;
  1061.                 FT_Set_Char_Size(ttb->ttb_Face, 0, px_size,72, 72);
  1062.                 DBG1("\tRescaled to %ld pixels height.", px_size);
  1063.  
  1064.                 if (!(cf = cache_find_font(ttb->ttb_RealTTRenderBase, name)))
  1065.                   cf = cache_add_font(ttb->ttb_RealTTRenderBase, name);
  1066.                 if (cf)
  1067.                   {
  1068.                     if (!(cs = cache_find_size(ttb->ttb_RealTTRenderBase, cf, size)))
  1069.                       cs = cache_add_size(ttb->ttb_RealTTRenderBase, cf, size);
  1070.                     if (cs) ttb->ttb_CurrentCache = cs;
  1071.                   }
  1072.  
  1073.                 /* global metrics calculation */
  1074.  
  1075.                 asc = (ttb->ttb_Face->size->metrics.ascender + 0x1F) >> 6;
  1076.                 desc = (0x1F - ttb->ttb_Face->size->metrics.descender) >> 6;
  1077.                 ttb->ttb_Ascender = asc + ((size - (asc + desc)) >> 1);
  1078.                 ttb->ttb_Descender = size - ttb->ttb_Ascender;
  1079.  
  1080.                 result = TRUE;
  1081.               }
  1082.             UnLock(testlock);
  1083.           }
  1084.         FreePooled(ttb->ttb_MemPool, filepath, MAX_PATH_LENGHT);
  1085.       }
  1086.     return result;
  1087.   }
  1088.  
  1089. /****** ttrender.library/TT_PutStr ******************************************
  1090. *
  1091. *   NAME
  1092. *       TT_PutStr -- Renders string into RastPort.
  1093. *
  1094. *   SYNOPSIS
  1095. *       success = TT_PutStr (string)
  1096. *                            A0
  1097. *
  1098. *       BOOL TT_PutStr (UBYTE*);
  1099. *
  1100. *   FUNCTION
  1101. *       Renders the string using current ttrender.library settings, and
  1102. *       current RastPort settings (pen, drawmode). String is rendered at
  1103. *       current RastPort (x, y) position, where 'y' means position of font
  1104. *       baseline. String is converted to Unicode according to
  1105. *       "ENV:ttfcodepage" mapping table. If there is no mapping table,
  1106. *       ISO-8859-1 mapping is used which is equal to ECMA Latin1 Amiga
  1107. *       standard.
  1108. *
  1109. *   INPUTS
  1110. *       string - NULL-terminated string to render to.
  1111. *
  1112. *   RESULT
  1113. *       TRUE if the string has been rendered.
  1114. *
  1115. *   EXAMPLE
  1116. *       \* write a text with pen 1 and transp. background at (100, 100) *\
  1117. *       \* rendering is done to a system window                         *\
  1118. *
  1119. *       SetAPen(win->RPort, 1);
  1120. *       SetDrMd(win->RPort, JAM1);
  1121. *       Move(win->RPort, 100, 100);
  1122. *       TT_SetModesTags(TTA_Window, win);
  1123. *       TT_PutStr("some text");
  1124. *
  1125. *   NOTES
  1126. *
  1127. *   BUGS
  1128. *
  1129. *   SEE ALSO
  1130. *       TT_PutStrTagList(), TT_SetModesTagList(), TT_PutUStr()
  1131. *
  1132. *****************************************************************************
  1133. *
  1134. */
  1135.  
  1136.  
  1137. __saveds BOOL TT_PutStr(struct TTRenderBase *ttb reg(a6), UBYTE *str reg(a0))
  1138.   {
  1139.     struct RenderEnv *re = &ttb->ttb_RenderEnv;
  1140.  
  1141.     if (re->re_TargetRPort && re->re_TargetCMap)
  1142.       {
  1143.         tt_putstr(ttb, re, re->re_TargetRPort->cp_x, re->re_TargetRPort->cp_y, str, FALSE);
  1144.         return TRUE;
  1145.       }
  1146.     return FALSE;
  1147.   }
  1148.  
  1149. /****** ttrender.library/TT_PutUStr *****************************************
  1150. *
  1151. *   NAME
  1152. *       TT_PutUStr -- Renders Unicode string into RastPort.
  1153. *
  1154. *   SYNOPSIS
  1155. *       success = TT_PutUStr (string)
  1156. *                             A0
  1157. *
  1158. *       BOOL TT_PutUStr (UWORD*);
  1159. *
  1160. *   FUNCTION
  1161. *       Renders the string using current ttrender.library (RastPort, ColorMap,
  1162. *       render mode), and RastPort settings (pen, drawmode). String is
  1163. *       rendered at current RastPort (x, y) position, where 'y' means position
  1164. *       of font baseline. String is an 16-bit Unicode one and should be
  1165. *       terminated with 16-bit zero.
  1166. *
  1167. *   INPUTS
  1168. *       string - 16-bit Unicode NULL-terminated string to render to.
  1169. *
  1170. *   RESULT
  1171. *       TRUE if the string has been rendered.
  1172. *
  1173. *   BUGS
  1174. *
  1175. *   SEE ALSO
  1176. *       TT_PutUStrTagList(), TT_SetModesTagList(), TT_PutStr()
  1177. *
  1178. *****************************************************************************
  1179. *
  1180. */
  1181.  
  1182.  
  1183. __saveds BOOL TT_PutUStr(struct TTRenderBase *ttb reg(a6), UWORD *ustr reg(a0))
  1184.   {
  1185.     struct RenderEnv *re = &ttb->ttb_RenderEnv;
  1186.  
  1187.     if (re->re_TargetRPort && re->re_TargetCMap)
  1188.       {
  1189.         tt_putstr(ttb, re, re->re_TargetRPort->cp_x, re->re_TargetRPort->cp_y, ustr, TRUE);
  1190.         return TRUE;
  1191.       }
  1192.     return FALSE;
  1193.   }
  1194.  
  1195.  
  1196. static ULONG parse_taglist(struct TTRenderBase *ttb, struct TagItem *taglist, struct RenderEnv *renv)
  1197.   {
  1198.     USELIB(UtilityBase);
  1199.     USELIB_DBG(DOSBase)
  1200.  
  1201.     struct TagItem *current_tag, *tag_pointer = taglist;
  1202.     BOOL rpset = FALSE, cmset = FALSE;
  1203.     ULONG tag_counter = 0;
  1204.  
  1205.     while (current_tag = NextTagItem(&tag_pointer))
  1206.       {
  1207.         switch (current_tag->ti_Tag)
  1208.           {
  1209.             case TTA_Antialias:
  1210.               renv->re_Antialias = current_tag->ti_Data;
  1211.               DBG1("\tAntialias %s", renv->re_Antialias ? (ULONG)"on" : (ULONG)"off");
  1212.               tag_counter++;
  1213.               break;
  1214.  
  1215.             case TTA_RastPort:
  1216.               renv->re_TargetRPort = (struct RastPort*)current_tag->ti_Data;
  1217.               DBG1("\tRastPort $%08lx", renv->re_TargetRPort);
  1218.               rpset = TRUE;
  1219.               tag_counter++;
  1220.               break;
  1221.  
  1222.             case TTA_ColorMap:
  1223.               renv->re_TargetCMap = (struct ColorMap*)current_tag->ti_Data;
  1224.               DBG1("\tColorMap $%08lx", renv->re_TargetCMap);
  1225.               cmset = TRUE;
  1226.               tag_counter++;
  1227.               break;
  1228.  
  1229.             case TTA_Screen:
  1230.               if (!rpset) renv->re_TargetRPort = &((struct Screen*)current_tag->ti_Data)->RastPort;
  1231.               if (!cmset) renv->re_TargetCMap = ((struct Screen*)current_tag->ti_Data)->ViewPort.ColorMap;
  1232.               DBG1("\tScreen $%08lx", current_tag->ti_Data);
  1233.               DBG2("\t[RPort $%08lx, CMap $%08lx]", renv->re_TargetRPort, renv->re_TargetCMap);
  1234.               tag_counter++;
  1235.               break;
  1236.  
  1237.             case TTA_Window:
  1238.               if (!rpset)renv->re_TargetRPort = ((struct Window*)current_tag->ti_Data)->RPort;
  1239.               if (!cmset)renv->re_TargetCMap = ((struct Window*)current_tag->ti_Data)->WScreen->ViewPort.ColorMap;
  1240.               DBG1("\tWindow $%08lx", current_tag->ti_Data);
  1241.               DBG2("\t[RPort $%08lx, CMap $%08lx]", renv->re_TargetRPort, renv->re_TargetCMap);
  1242.               tag_counter++;
  1243.               break;
  1244.           }
  1245.       }
  1246.   }
  1247.  
  1248. /****** ttrender.library/TT_PutStrTagList ***********************************
  1249. *
  1250. *   NAME
  1251. *       TT_PutStrTagList -- Renders string into RastPort with local settings.
  1252. *
  1253. *   SYNOPSIS
  1254. *       success = TT_PutStrTagList (string, taglist)
  1255. *                                   A0      A1
  1256. *
  1257. *       BOOL TT_PutStrTagList (UBYTE*, struct TagItem*);
  1258. *
  1259. *       success = TT_PutStrTags (string, Tag1, ...)
  1260. *
  1261. *       BOOL TT_PutStrTags (UBYTE*, Tag, ...);
  1262. *
  1263. *   FUNCTION
  1264. *       Renders the string allowing temporary override of current
  1265. *       ttrender.library settings, and current RastPort settings. Attributes
  1266. *       given in the taglist have local precedence over global
  1267. *       ttrender.library settings set by TT_SetModesTagList() call. Check
  1268. *       TT_SetModesTagList() docs for a list of tags.
  1269. *
  1270. *   INPUTS
  1271. *       string - NULL-terminated string to render to.
  1272. *
  1273. *       taglist - local attributes valid only in this function call.
  1274. *
  1275. *   RESULT
  1276. *       TRUE if the string has been rendered.
  1277. *
  1278. *   EXAMPLE
  1279. *
  1280. *       \* Turn antialias mode on globally *\
  1281. *
  1282. *       TT_SetModesTags(TTA_Antialias, TRUE);
  1283. *
  1284. *       TT_PutStr("some text");           \* this text will be antialiased *\
  1285. *       TT_PutStrTags("another text",
  1286. *         TTA_Antialias, FALSE,           \* this text won't (locally      *\
  1287. *         TAG_END);                       \* switched off)                 *\
  1288. *       TT_PutStr("third text");          \* this text will be antialiased *\
  1289. *
  1290. *   NOTES
  1291. *
  1292. *   BUGS
  1293. *
  1294. *   SEE ALSO
  1295. *       TT_PutStr(), TT_SetModesTagList()
  1296. *
  1297. *****************************************************************************
  1298. *
  1299. */
  1300.  
  1301. __saveds BOOL TT_PutStrTagList(struct TTRenderBase *ttb reg(a6), UBYTE *str reg(a0), struct TagItem *taglist reg(a1))
  1302.   {
  1303.     USELIB(SysBase);
  1304.     USELIB_DBG(DOSBase)
  1305.     struct RenderEnv local;
  1306.  
  1307.     DBG("Local TT_PutStrTagList() settings change:");
  1308.     CopyMem(&ttb->ttb_RenderEnv, &local, sizeof(struct RenderEnv));
  1309.     parse_taglist(ttb, taglist, &local);
  1310.     if (local.re_TargetRPort && local.re_TargetCMap)
  1311.       {
  1312.         tt_putstr(ttb, &local, local.re_TargetRPort->cp_x, local.re_TargetRPort->cp_y, str, FALSE);
  1313.         return TRUE;
  1314.       }
  1315.     return FALSE;
  1316.   }
  1317.  
  1318. /****** ttrender.library/TT_PutUStrTagList **********************************
  1319. *
  1320. *   NAME
  1321. *       TT_PutUStrTagList -- Renders 16-bit Unicode string into RastPort with
  1322. *                           local settings.
  1323. *
  1324. *   SYNOPSIS
  1325. *       success = TT_PutUStrTagList (string, taglist)
  1326. *                                   A0      A1
  1327. *
  1328. *       BOOL TT_PutUStrTagList (UWORD*, struct TagItem*);
  1329. *
  1330. *       success = TT_PutUStrTags (string, Tag1, ...)
  1331. *
  1332. *       BOOL TT_PutUStrTags (UWORD*, Tag, ...);
  1333. *
  1334. *   FUNCTION
  1335. *       Renders the 16-bit Unicode string allowing temporary override of
  1336. *       current ttrender.library settings, and current RastPort settings.
  1337. *       Attributes given in the taglist have local precedence over global
  1338. *       ttrender.library settings set by TT_SetModesTagList() call. Check
  1339. *       TT_SetModesTagList() docs for a list of tags.
  1340. *
  1341. *   INPUTS
  1342. *       string - NULL-terminated 16-bit Unicode string to render to.
  1343. *
  1344. *       taglist - local attributes valid only in this function call.
  1345. *
  1346. *   RESULT
  1347. *       TRUE if the string has been rendered.
  1348. *
  1349. *   NOTES
  1350. *
  1351. *   BUGS
  1352. *
  1353. *   SEE ALSO
  1354. *       TT_PutUStr(), TT_SetModesTagList()
  1355. *
  1356. *****************************************************************************
  1357. *
  1358. */
  1359.  
  1360. __saveds BOOL TT_PutUStrTagList(struct TTRenderBase *ttb reg(a6), UWORD *str reg(a0), struct TagItem *taglist reg(a1))
  1361.   {
  1362.     USELIB(SysBase);
  1363.     USELIB_DBG(DOSBase)
  1364.     struct RenderEnv local;
  1365.  
  1366.     DBG("Local TT_PutUStrTagList() settings change:");
  1367.     CopyMem(&ttb->ttb_RenderEnv, &local, sizeof(struct RenderEnv));
  1368.     parse_taglist(ttb, taglist, &local);
  1369.     if (local.re_TargetRPort && local.re_TargetCMap)
  1370.       {
  1371.         tt_putstr(ttb, &local, local.re_TargetRPort->cp_x, local.re_TargetRPort->cp_y, str, TRUE);
  1372.         return TRUE;
  1373.       }
  1374.     return FALSE;
  1375.   }
  1376.  
  1377. /****** ttrender.library/TT_SetModesTagList *********************************
  1378. *
  1379. *   NAME
  1380. *       TT_SetModesTagList -- Sets global rendering settings.
  1381. *
  1382. *   SYNOPSIS
  1383. *       count = TT_SetModesTagList (taglist)
  1384. *                                   A0
  1385. *
  1386. *       ULONG TT_SetModesTagList (struct TagItem*);
  1387. *
  1388. *       count = TT_SetModesTags (Tag1, ...)
  1389. *
  1390. *       ULONG TT_SetModesTags (Tag, ...);
  1391. *
  1392. *   FUNCTION
  1393. *       Sets global (per library opening) render engine settings. Every
  1394. *       following TT_PutStr() / TT_PutUStr() call will use these settings.
  1395. *       They can by overriden temporarily however, with TT_PutStrTagList() /
  1396. *       TT_PutUStrTagList() calls. Here is a list of attributes:
  1397. *
  1398. *       TTA_RastPort - (struct RastPort*) - Destination RastPort for
  1399. *         rendering. The library will adhere to this RastPort settings like
  1400. *         draw mode, pens, current pen position.
  1401. *
  1402. *       TTA_ColorMap - (struct ColorMap*) - ColorMap used to convert pen
  1403. *         number to RGB color value.
  1404. *
  1405. *       TTA_Screen - (struct Screen*) - useful shortcut for TTA_RastPort and
  1406. *         TTA_ColorMap, automatically sets screen ColorMap and screen
  1407. *         RastPort.
  1408. *
  1409. *       TTA_Window - (struct Window*) - useful shortcut for TTA_RastPort and
  1410. *         TTA_ColorMap, automatically sets window ColorMap and window
  1411. *         RastPort.
  1412. *
  1413. *       TTA_Antialias - (BOOL) - controls antialiasing (on or off).
  1414. *
  1415. *   INPUTS
  1416. *       taglist - the list of global attributes.
  1417. *
  1418. *   RESULT
  1419. *       counter - the count of recognized tags.
  1420. *
  1421. *   NOTES
  1422. *       TTA_RastPort and TTA_ColorMap attributes have precedence over
  1423. *       TTA_Screen and TTA_Window ones. It can be useful if one wants to use
  1424. *       window/screen ColorMap but separate RastPort. An example:
  1425. *
  1426. *       TT_SetModesTags(TTA_Window, win, TTA_RastPort, my_rport, TAG_END);
  1427. *
  1428. *       It will set window colormap and 'my_rport' as targets. Note that the
  1429. *       precedence is based on tag values, not on tags order. So ordering of
  1430. *       the tags is meaningless for the function.
  1431. *
  1432. *   BUGS
  1433. *
  1434. *   SEE ALSO
  1435. *       TT_PutStr(), TT_SetModesTagList()
  1436. *
  1437. *****************************************************************************
  1438. *
  1439. */
  1440.  
  1441. __saveds ULONG TT_SetModesTagList(struct TTRenderBase *ttb reg(a6), struct TagItem *taglist reg(a0))
  1442.   {
  1443.     USELIB_DBG(DOSBase)
  1444.  
  1445.     DBG("Global settings change:");
  1446.     return (parse_taglist(ttb, taglist, &ttb->ttb_RenderEnv));
  1447.   }
  1448.  
  1449. /****** ttrender.library/TT_GetFontAttrsTagList *****************************
  1450. *
  1451. *   NAME
  1452. *       TT_GetFontAttrsTagList -- Gets current font attributes (V2).
  1453. *
  1454. *   SYNOPSIS
  1455. *       count = TT_GetFontAttrsTagList (taglist)
  1456. *                                       A0
  1457. *
  1458. *       ULONG TT_GetFontAttrsTagList (struct TagItem*);
  1459. *
  1460. *       count = TT_GetFontAttrsTags (Tag1, ...)
  1461. *
  1462. *       ULONG TT_GetFontAttrsTags (Tag, ...);
  1463. *
  1464. *   FUNCTION
  1465. *       Gets current (set by last SetFont() call) font attributes (global
  1466. *       metrics mainly). The value of every attribute is written to an ULONG
  1467. *       pointed by ti_Data field of the TagItem. Here is a list of attributes:
  1468. *
  1469. *       TTFA_Ascender - This is a distance (in pixels) between the baseline
  1470. *         and top elements of the font (typically these elements are accents
  1471. *         of capital letters). NOTE: many shareware TT fonts have wrong ascen-
  1472. *         der value.
  1473. *
  1474. *       TTFA_Descender - This is a distance (in pixels) between the baseline
  1475. *         and bottom elements of the font (typically in letters 'p', 'q', 'g'
  1476. *         etc.). NOTE: many shareware TT fonts have wrong descender value.
  1477. *         Descender value is typically negative (as bottom elements usually
  1478. *         are placed below the baseline).
  1479. *
  1480. *       NOTE: TTFA_Ascender and TTFA_Descender are guarranted to fulfill
  1481. *       following formula: ascender - descender = font height.
  1482. *
  1483. *   INPUTS
  1484. *       taglist - the list of attributes.
  1485. *
  1486. *   RESULT
  1487. *       counter - the count of recognized tags.
  1488. *
  1489. *   NOTES
  1490. *
  1491. *   BUGS
  1492. *
  1493. *   SEE ALSO
  1494. *       TT_SetFont()
  1495. *
  1496. *****************************************************************************
  1497. *
  1498. */
  1499.  
  1500. __saveds ULONG TT_GetFontAttrsTagList(struct TTRenderBase *ttb reg(a6), struct TagItem *taglist reg(a0))
  1501.   {
  1502.     USELIB(UtilityBase);
  1503.     USELIB_DBG(DOSBase)
  1504.  
  1505.     struct TagItem *current_tag, *tag_pointer = taglist;
  1506.     ULONG tag_counter = 0;
  1507.  
  1508.     DBG("TT_GetFontAttrsTagList()");
  1509.  
  1510.     while (current_tag = NextTagItem(&tag_pointer))
  1511.       {
  1512.         switch (current_tag->ti_Tag)
  1513.           {
  1514.             case TTFA_Ascender:
  1515.               *(ULONG*)current_tag->ti_Data = ttb->ttb_Ascender;
  1516.               DBG2("\tTTFA_Ascender (%ld) written at %08lx", ttb->ttb_Ascender, current_tag->ti_Data);
  1517.               tag_counter++;
  1518.               break;
  1519.  
  1520.             case TTFA_Descender:
  1521.               *(ULONG*)current_tag->ti_Data = ttb->ttb_Descender;
  1522.               DBG2("\tTTFA_Descender (%ld) written at %08lx", ttb->ttb_Descender, current_tag->ti_Data);
  1523.               tag_counter++;
  1524.               break;
  1525.           }
  1526.       }
  1527.     return tag_counter;
  1528.   }
  1529.  
  1530. /****** ttrender.library/TT_StrWidth ****************************************
  1531. *
  1532. *   NAME
  1533. *       TT_StrWidth -- Gets string width in pixels (V2).
  1534. *
  1535. *   SYNOPSIS
  1536. *       width = TT_StrWidth(string)
  1537. *                           A0
  1538. *
  1539. *       ULONG TT_StrWidth (UBYTE*);
  1540. *
  1541. *   FUNCTION
  1542. *       Calculates the pixel width of given string written with current font.
  1543. *       Takes kerning into account. String will be mapped to Unicode using
  1544. *       "ENV:ttfcodepage" table (see TT_PutStr() docs).
  1545. *
  1546. *   INPUTS
  1547. *       string - the width of this string will be calculated.
  1548. *
  1549. *   RESULT
  1550. *       width - the width of the string in pixels.
  1551. *
  1552. *   NOTES
  1553. *
  1554. *   BUGS
  1555. *
  1556. *   SEE ALSO
  1557. *       TT_PutStr(), TT_SetFont()
  1558. *
  1559. *****************************************************************************
  1560. *
  1561. */
  1562.  
  1563. __saveds ULONG TT_StrWidth(struct TTRenderBase *ttb reg(a6), UBYTE *string reg(a0))
  1564.   {
  1565.     return (tt_strwidth(ttb, &ttb->ttb_RenderEnv, string, FALSE));
  1566.   }
  1567.  
  1568. /****** ttrender.library/TT_UStrWidth ***************************************
  1569. *
  1570. *   NAME
  1571. *       TT_UStrWidth -- Gets Unicode 16-bit string width in pixels (V2).
  1572. *
  1573. *   SYNOPSIS
  1574. *       width = TT_UStrWidth(string)
  1575. *                            A0
  1576. *
  1577. *       ULONG TT_UStrWidth (UWORD*);
  1578. *
  1579. *   FUNCTION
  1580. *       Calculates the pixel width of given 16-bit Unicode string written
  1581. *       with current font. Takes kerning into account.
  1582. *
  1583. *   INPUTS
  1584. *       string - the width of this 16-bit Unicode string will be calculated.
  1585. *
  1586. *   RESULT
  1587. *       width - the width of the string in pixels.
  1588. *
  1589. *   NOTES
  1590. *
  1591. *   BUGS
  1592. *
  1593. *   SEE ALSO
  1594. *       TT_PutUStr(), TT_SetFont()
  1595. *
  1596. *****************************************************************************
  1597. *
  1598. */
  1599.  
  1600. __saveds ULONG TT_UStrWidth(struct TTRenderBase *ttb reg(a6), UWORD *string reg(a0))
  1601.   {
  1602.     return (tt_strwidth(ttb, &ttb->ttb_RenderEnv, string, TRUE));
  1603.   }
  1604.  
  1605.